//
//  InTrainingViewModel.swift
//  DaRings
//
//  Created by 魔样科技 on 2022/11/4.
//

import Foundation
import RxCocoa
import MYModule
import HandyJSON
import CRPSmartRing



open class InTrainingViewModel: NSObject {
    
    /// UI 显示
    public var model: InTrainingModel?
    
    /// 运动记录
    public var trainingModel: TrainingModel?
    
   
    public init(type: TrainingType, golaType: TrainingTypeContent?, startTime: Int) {
        super.init()
        
        if let trainingModel = TrainingModel.last(type: type.rawValue, golaType?.goalType.rawValue, startTime: startTime) {
            if trainingModel.endTime == 0 {
                self.trainingModel = trainingModel
            }
        }
        
        // 新开无目标设置的运动
        if self.trainingModel == nil {
            let trainingModel = TrainingModel.newTraining(type: type.rawValue)
            trainingModel.type = type.rawValue
            trainingModel.adress = DeviceInfo.current().adress ?? ""
            
            if let golaType = golaType {
                trainingModel.goalType = golaType.rawValue
            }
            trainingModel.updateData()
            
            self.trainingModel = trainingModel
        }
        
        
        
        // 距离实时转换
        let distanceTitle = Unit.sharedInstance.myType == .metric ? "training_in_training_distance_km".language : "training_in_training_distance_miles".language
        let distance: [String: Any] = [
            "title": distanceTitle,
            "contentType": TrainingTypeContent.distance]
        
        let time: [String: Any] = ["title": "training_total_time".language,
                                   "contentType": TrainingTypeContent.time]
        
        let calories: [String: Any] = ["title": "training_in_training_calories".language,
                                       "contentType": TrainingTypeContent.calorie, "unit": TrainingTypeContent.calorie.targetUnit!]
        
        let paceTitle = Unit.sharedInstance.myType == .metric ? "training_in_training_pace".language : "training_in_training_imperial_pace".language
        let pace: [String: Any] = ["title": paceTitle,
                                   "contentType": TrainingTypeContent.pace]
        
        let step: [String: Any] = ["title": "training_total_steps".language,
                                   "contentType": TrainingTypeContent.step]
        
        let heartRate: [String: Any] = ["title": "training_in_training_heart_rate".language,
                                        "contentType": TrainingTypeContent.heartRate]
        
        guard var items = [TrainingItemModel].deserialize(from: [time, calories, distance, pace, step, heartRate])?.compactMap ({ $0 }) else {
            return
        }
        
        self.model = InTrainingModel()
       
        /// 头部显示算法
        /// 首先判定目标设置是设的哪一种
        /// 如果没有目标设置，根据运动类型支持的内容排列，优先级是距离 > 时长> ...
    
        guard let trainingModel = trainingModel else {
            return
        }
        modelWithTrainingModel(trainingModel, items: &items)

        updateData()
   
    }
    
    /// 设置运动目标的model
    /// - Parameters:
    ///   - goalType: 目标类型
    ///   - items: 子数据
    public func modelWithTrainingModel(_ trainingModel: TrainingModel, items: inout [TrainingItemModel]) {
        
        guard let trainingType = TrainingType(rawValue: trainingModel.type) else {
            return
        }
        
        // 删除 锻炼类型不支持的item
        items = items.filter({ item in
            
            trainingType.contents.contains(where: { item.contentType == $0 })
            
        })
    
        
        guard let goalType = CRPTrainingGoalType(rawValue: trainingModel.goalType)?.trainingContentType else {
            modelWithTrainingType(trainingType, items: &items)
            return
        }
        
        if goalType == .unkown {
            modelWithTrainingType(trainingType, items: &items)
            return
        }
        
        // 目标设置
        if let targetItem = items.filter ({ $0.contentType == goalType }).first {
            
            self.updateGoal(item: targetItem, goalType: goalType, goal: Double(trainingModel.goal))
            
            self.model?.targetItem = targetItem
            items.removeAll(targetItem)
            
        }
        
        /// 副item，有时长/距离显示时候才赋值 viceItem, 设置时长时, timeItem = nil targetItem = 时长
        if self.model?.targetItem?.contentType == .time {
            if let timeItem = items.filter({ $0.contentType == .distance }).first {
                
                self.model?.viceItem = timeItem
                items.removeAll(timeItem)
            }
            
        } else {
            if let timeItem = items.filter({ $0.contentType == .time }).first, items.count > 2 {
                
                self.model?.viceItem = timeItem
                items.removeAll(timeItem)
            }
        }
        
        modelWithTrainingType(trainingType, items: &items)
        
    }
    
    /// 未设置目标的model，根据运动类型判断
    /// - Parameters:
    ///   - trainingType: 运动类型
    ///   - items: 子数据
   fileprivate func modelWithTrainingType(_ trainingType: TrainingType, items: inout [TrainingItemModel]) {
        
        let contents = trainingType.contents
        
       var newItems = items.filter {
            
            contents.contains($0.contentType)
        }
       
       if let _ = self.model?.targetItem {
           self.model?.items = newItems
           return
       }
       
       if contents.contains(.distance) {
           
           if let targetItem = newItems.filter({ $0.contentType == .distance }).first {
               
               self.model?.targetItem = targetItem
               newItems.removeAll(targetItem)
               
           }
           
           // 副主题有时间并且items >2 副主题都显示时间
           if let viceItem = newItems.filter({ $0.contentType == .time }).first, newItems.count > 2 {
               self.model?.viceItem = viceItem
               newItems.removeAll(viceItem)
           }
           
           
       } else {
           
           if contents.contains(.time) {
               // 没有距离的都显示时长
               if let targetItem = newItems.filter({ $0.contentType == .time }).first, newItems.count > 2 {
                   self.model?.targetItem = targetItem
                   newItems.removeAll(targetItem)
               }
           }
       }
           
        self.model?.items = newItems
       
   }
    
}

extension InTrainingViewModel {
    
    public func updateData() {
        
        guard let trainingModel = self.trainingModel else { return }
        guard let trainingType = TrainingType(rawValue: trainingModel.type) else { return }
        updateData(of: trainingType)
        
    }
    
    public func updateData(of trainingType: TrainingType) {
        
        let contents = trainingType.contents
        contents.forEach {
            self.updateData(of: $0)
        }
        
    }

    /// 跟新对应的数据
    /// - Parameter goalType: 运动类型
    public func updateData(of contentType: TrainingTypeContent) {
        
        guard let trainingModel = self.trainingModel else { return }
        
        switch contentType {
            
        case .time:
            
            updateTime(trainingModel.vaildTime)
            break
            
        case .step:
            updateStep(trainingModel.step)
            break
            
        case .heartRate:
            
            updateHeartRate(trainingModel.heartRateAvg)
            break
            
        case .calorie:
            
            updateCalorise(trainingModel.kcal)
            break
            
        case .distance:
            
            updateDistance(trainingModel.distance)
            break
            
        case .pace:
            
            updatePace(trainingModel.distance, seconds: trainingModel.vaildTime)
            break
            
        case .unkown:
            break
        }
        
    }
    
    public var stepItem: TrainingItemModel? {
        
       return model?.subItems.filter({ $0.contentType == .step }).first
        
    }
    
    public var calorieItem: TrainingItemModel? {
        
        return model?.subItems.filter({ $0.contentType == .calorie }).first
         
    }
    
    public func updateDistance(_ distance: Int) {
        log.debug("更新距离：\(distance)")
        guard let distanceItem = model?.subItems.filter({ $0.contentType == .distance }).first else {
            return
        }
        
        let tuple = Unit.sharedInstance.distanceOf(Double(distance), unit: (.km, .miles))
        
        let distance = ceil(tuple.distance * 100) / 100
        distanceItem.currentData = distance
        distanceItem.unit = tuple.unitType.name
       
    }
    
    
    
    public func updateTime(_ seconds: Int) {
        
        guard let timeItem = model?.subItems.filter({ $0.contentType == .time }).first else {
            return
        }
        
        timeItem.currentData = Double(seconds)
        
        trainingModel?.vaildTime = seconds
        trainingModel?.updateData()
       
    }
    
    public func updatePace(_ distance: Int, seconds: Int) {
        
        guard let paceItem = model?.subItems.filter({ $0.contentType == .pace }).first else {
            return
        }
        let tuple = Unit.sharedInstance.paceOf(distance: Double(distance), seconds: seconds)
        paceItem.currentData = tuple.paceMinute
        paceItem.unit = tuple.unit
       
    }
    

    public func updateCalorise(_ calorise: Int) {
        
        guard let caloriseItem = model?.subItems.filter({ $0.contentType == .calorie }).first else {
            return
        }
        
        caloriseItem.currentData = Double(calorise)
        trainingModel?.kcal = calorise
        
    }
    
    public func updateStep(_ step: Int) {
        guard let stepItem = model?.subItems.filter({ $0.contentType == .step }).first else {
            return
        }
        
        stepItem.currentData = Double(step)
        trainingModel?.step = step
    }
    
    public func updateHeartRate(_ heartRate: Int) {
        guard let heartRateItem = model?.subItems.filter({ $0.contentType == .heartRate }).first else {
            return
        }
        
        heartRateItem.currentData = Double(heartRate)
        
        guard let trainingModel = self.trainingModel else { return }
        
        let nowTime = Date().timeIntervalSince1970
        let interval = nowTime - trainingModel.heartRatesUpdateTime
        
        // 每10秒截取一个心率
        if interval >= 10 {
            trainingModel.heartRates.append(heartRate)
            
            // 计算平均心率
            var avgHeart = 0
            var totalHeart = 0
            var heartCount = 0
            for heart in trainingModel.heartRates {
                if heart > 0 {
                    totalHeart += heart
                    heartCount += 1
                }
            }
            if heartCount > 0 {
                avgHeart = totalHeart/heartCount
            }
            
            trainingModel.heartRateAvg = avgHeart
            
            trainingModel.heartRatesUpdateTime = nowTime
            trainingModel.updateData()
        }
    }
    

    public func saveData() {
        
        trainingModel?.endTime = Int(Date().timeIntervalSince1970)
        trainingModel?.achievement = self.goalAchievement
        trainingModel?.updateData()
    }
    
    fileprivate func updateGoal(item: TrainingItemModel, goalType: TrainingTypeContent, goal: Double) {
        

        switch goalType {
        case .distance:
            
            let tuple = Unit.sharedInstance.goalDistance(goal)
            item.targetData = tuple.distance/1000.0
            break
            
        case .time:
            
            item.targetData = goal
            break
            
        case .pace:
            
            item.targetData = goal
            break
            
        case .calorie:
            let pace = Unit.sharedInstance.goalMetricPace(goal)
            item.targetData = pace
            break
            
        default:
            break
        }
        
    }
    
    
}

extension InTrainingViewModel {
    
    public var goalAchievement: Bool {
        
        var achievement: Bool = false
        
        guard let trainingModel = self.trainingModel, let goalType = CRPSmartRing.CRPTrainingGoalType(rawValue: trainingModel.goalType)?.trainingContentType else { return achievement }
        
        switch goalType {
        case .unkown:
            break
        case .distance:
            achievement = trainingModel.distance >= trainingModel.goal
            break
        case .time:
            achievement = trainingModel.vaildTime >= trainingModel.goal
        case .pace:
            
            let km: Double = Double(trainingModel.distance)/1000.0
            var pace = 0.0
            if km != 0 {
                if Unit.sharedInstance.myType == .metric {
                    pace = (Double(trainingModel.vaildTime) / 60.0) / km
                } else {
                    pace = (Double(trainingModel.vaildTime) / 60.0) / ((Double(trainingModel.distance) * 100 / 16093) / 10.0)
                }
            }
            
            achievement = pace < Double(trainingModel.goal)
            break
        case .calorie:
            achievement = trainingModel.kcal >= trainingModel.goal
        default:
            break
        }
        
        return achievement
        
    }
    
}
